//
// Created by Asus on 2025/6/9.
//
//
// Created by l30039280 on 2025/6/5.
//
#include <bemapiset.h>
#include <iostream>
#include "gtest/gtest.h"
#include <string>
#include <gmock/gmock.h>

class User {

public:
    User() {
    };
    ~User() {
    };
public:
    // 登录
    virtual bool Login(const std::string& username, const std::string& password) = 0;
    // 支付
    virtual bool Pay(int money) = 0;
    // 是否登录
    virtual bool Online() = 0;
};

class Biz {

public:
    void SetUser(User* user) {

        _user = user;
    }

    std::string pay(const std::string& username, const std::string& password, int money) {
        std::string ret;
        if (!_user) {
            ret = "pointer is null.";
            return ret;
        }
        if (!_user->Online()) {
            ret = "logout status.";
            // 尚未登录，要求登录
            if (!_user->Login(username, password)) {
                // 登录失败
                ret += "login error.";
                return ret;
            } else {
                // 登录成功
                ret += "login success.";
            }
        } else {
            // 已登录
            ret = "login.status";
        }
        if (!_user->Pay(money)) {
            ret += "pay error.";
        } else {
            ret += "pay success.";
        }
        return ret;
    }
private:
    User* _user;
};

using namespace testing;
using namespace std;

class TestUser : public User {
public:
    MOCK_METHOD2(Login, bool(const std::string&, const std::string&));
    MOCK_METHOD1(Pay, bool(int));
    MOCK_METHOD0(Online, bool());
};

// 测试用例1: 用户已登录状态下的支付
TEST(BizTest, OnlineUserPaySuccess) {
    TestUser test_user;
    EXPECT_CALL(test_user, Online()).Times(1).WillOnce(Return(TRUE));
    EXPECT_CALL(test_user, Pay(1)).WillOnce(Return(true));

    Biz biz;
    biz.SetUser(&test_user);
    std::string ret = biz.pay("user", "pass", 1);
    EXPECT_EQ(ret, "login.statuspay success.");
}

// 测试用例2: 用户登录失败
TEST(BizTest, LoginFailure) {
    TestUser test_user;
    // 设置预期：用户不在线，登录失败
    EXPECT_CALL(test_user, Online()).WillOnce(Return(false));
    EXPECT_CALL(test_user, Login("admin", "password")).WillOnce(Return(false));

    Biz biz;
    biz.SetUser(&test_user);
    std::string ret = biz.pay("admin", "password", 1);
    EXPECT_EQ(ret, "logout status.login error.");
}

// 测试用例3: 用户登录成功并支付成功
TEST(BizTest, LoginSuccessThenPaySuccess) {
    TestUser test_user;
    // 设置预期：用户不在线，登录成功，支付成功
    EXPECT_CALL(test_user, Online()).WillOnce(Return(false));
    EXPECT_CALL(test_user, Login(StrNe("admin"), _)).WillOnce(Return(true));
    EXPECT_CALL(test_user, Pay(100)).WillOnce(Return(true));

    Biz biz;
    biz.SetUser(&test_user);
    std::string ret = biz.pay("user", "pass123", 100);
    EXPECT_EQ(ret, "logout status.login success.pay success.");
}

// 测试用例4: 多次支付测试
TEST(BizTest, MultiplePayments) {
    TestUser test_user;
    // 设置预期：用户不在线，登录成功
    // 支付5次：前两次成功，后三次失败
    EXPECT_CALL(test_user, Online()).WillOnce(Return(false));
    EXPECT_CALL(test_user, Login(StrNe("admin"), _)).WillOnce(Return(true));
    EXPECT_CALL(test_user, Pay(_))
        .Times(3) // 实际调用3次
        .WillOnce(Return(true))
        .WillOnce(Return(true))
        .WillOnce(Return(false));

    Biz biz;
    biz.SetUser(&test_user);

    // 第一次支付
    std::string ret1 = biz.pay("user", "pass", 50);
    EXPECT_EQ(ret1, "logout status.login success.pay success.");

    // 第二次支付（用户已登录）
    std::string ret2 = biz.pay("user", "pass", 30);
    EXPECT_EQ(ret2, "login.statuspay success.");

    // 第三次支付（用户已登录，支付失败）
    std::string ret3 = biz.pay("user", "pass", 20);
    EXPECT_EQ(ret3, "login.statuspay error.");
}

// 主函数
int main(int argc, char **argv) {
    // 初始化Google Test框架
    InitGoogleTest(&argc, argv);
    // 运行所有测试
    return RUN_ALL_TESTS();
}